\documentclass{beamer}
\usepackage{ctex, hyperref}
\usepackage[T1]{fontenc}

% other packages
\usepackage{latexsym,amsmath,xcolor,multicol,booktabs,calligra}
\usepackage{graphicx,pstricks,listings,stackengine}
\usepackage{subfigure}
\usepackage{multirow}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{caption}
\usepackage{tikz}

\newcommand{\highlightedhref}[2]{\href{#1}{\textcolor{blue}{\underline{#2}}}}

\definecolor{darkgreen}{rgb}{0,0.4,0}

\author[第 1 组]{第 1 组}
\title{OpenHarmony 任务 3}
\subtitle{为 Assembler 类添加 RISCV R-型指令支持}
\institute{中国科学院大学计算机科学与技术学院}
\date{2024年1月12日}
\usepackage{UCAS}

% defs
\def\cmd#1{\texttt{\color{red}\footnotesize $\backslash$#1}}
\def\env#1{\texttt{\color{blue}\footnotesize #1}}
\definecolor{deepblue}{rgb}{0,0,0.5}
\definecolor{deepred}{rgb}{0.6,0,0}
\definecolor{deepgreen}{rgb}{0,0.5,0}
\definecolor{halfgray}{gray}{0.55}

\lstset{
    basicstyle=\ttfamily\small,
    keywordstyle=\bfseries\color{deepblue},
    emphstyle=\ttfamily\color{deepred},    % Custom highlighting style
    stringstyle=\color{deepgreen},
    numbers=left,
    numberstyle=\small\color{halfgray},
    rulesepcolor=\color{red!20!green!20!blue!20},
    frame=shadowbox,
}

\begin{document}

\heiti
\begin{frame}
    \titlepage
    \begin{figure}[htpb]
        \begin{center}
            \includegraphics[width=0.2\linewidth]{pic/CAS_Logo.png}
        \end{center}
    \end{figure}
\end{frame}

% 总目录
% \begin{frame}
%     \tableofcontents[sectionstyle=show,subsectionstyle=show/shaded/hide,subsubsectionstyle=show/shaded/hide]
% \end{frame}

\section{组员介绍}

\begin{frame}{组员介绍}
    \begin{itemize}
        \item \highlightedhref{https://gitee.com/llh730}{@李龙昊}（llh730）
        \item \highlightedhref{https://gitee.com/soraneko}{@陶思成}（soraneko）
        \item \highlightedhref{https://gitee.com/MiaoHao-oops}{@郝淼}（MiaoHao-oops）        
    \end{itemize}
\end{frame}

\section{任务目标回顾}


\begin{frame}{Arkcompiler}

    \begin{columns}[t]
        \begin{column}{0.5\textwidth}

            {\small \quad arkcompiler(图\ref{fig:arkcompiler})是华为推出的首个完全自主研发的编译器平台，支持将javascript、typescript翻译为方舟字节码(arkcompiler bytecode)。}

            \begin{figure}
                \centering
                \includegraphics[width=0.85\textwidth]{pic/arkcompiler.png}
                \caption{armkcompiler架构图}
                \label{fig:arkcompiler}
            \end{figure}
        \end{column}
        \begin{column}{0.5\textwidth}

            {\small \vfill \quad 为了让机器能够正确的执行对应的方舟字节码，其需要将方舟字节码翻译为机器指令，这就是arkcom piler\_ets\_runtime组件的作用之一。}

            \vspace{0.5cm}

            {\small \quad 不同架构的硬件需要适配不同的翻译规则，我们实现的Assembler Riscv64类， \textcolor{red}{为ets\_runtime增加了生成RISCV架构下机器指令的支持。}}
        
        \end{column}
    \end{columns}
\end{frame}

\begin{frame}{Assembler 类}
    % 介绍Assembler
    \vspace{0.5cm}
    {\small \quad Assembler将方舟字节码翻译为指定架构下的二进制码,其运行时流程如图\ref{fig: ark-ts-arch}和图\ref{fig: assembler-ts-arch}所示}
    \vspace{-0.5cm}
    \begin{columns}[t]
        \begin{column}{0.5\textwidth}
            \begin{figure}
            \centering
            \begin{tikzpicture}
              % 绘制图表内容
              \node[inner sep=0pt] (image) at (0,0) {\includegraphics[width=0.9\textwidth]{pic/ark-ts-arch.png}};
              % 绘制红色框
              \draw[red, thick] (0.8,0.85) rectangle (2.3,1.2);
            % 绘制红色箭头
            \draw[red, thick, ->] (2.5,1.05) -- +(1.3,-0.6);
            \end{tikzpicture}
            \caption{arkcompiler运行时架构图}
            \label{fig: ark-ts-arch}
            \end{figure}
            
        \end{column}
        \begin{column}{0.5\textwidth}
            % 第二个图表
            \begin{figure}
                \vspace{2cm}
                \begin{tikzpicture}
                % 绘制图表内容
                \node[inner sep=0pt,yshift=1cm] (image) at (0,0) {\includegraphics[width=0.9\textwidth]{pic/assembler-ts-arch.png}};
              \end{tikzpicture}
              \caption{assembler运行时流程图}
              \label{fig: assembler-ts-arch}
            \end{figure}
        \end{column}
    \end{columns}    

\end{frame}

\begin{frame}{RISCV32I与RISCV64I}
    % 介绍RISCV32I和RISCV64I

    {\small \quad RISCV32I 指令集中的指令结构相对比较统一，共有六种类型的指令。RISCV64I指令集中的指令结构也与其一致，如图\ref{fig:riscv-all-inst}所示：}
    
    \begin{figure}
        \centering
        \includegraphics[width=0.85\textwidth]{pic/riscv-all-inst.jpg}
        \caption{RISCV(32/64)I 指令集}
        \label{fig:riscv-all-inst}
    \end{figure}
    
\end{frame}

\begin{frame}{RISCV(32/64)I-R}
    % 介绍RISCVI-R

    {\small \quad 而我们需要实现的，是RISCV(32/64)I中的15条R型指令，包含常见的加减运算、位运算和左移右移操作。具体指令如图\ref{fig:rv32i-inst}，\ref{fig:rv64i-inst}所示：}

    \begin{figure}
        \centering
        \includegraphics[width=0.8\textwidth]{pic/rv32i-inst.png}
        \caption{RISCV32I-R}
        \label{fig:rv32i-inst}
    \end{figure}

    \begin{figure}
        \centering
        \includegraphics[width=0.8\textwidth]{pic/rv64i-inst.png}
        \caption{RISCV64I-R}
        \label{fig:rv64i-inst}
    \end{figure}
\end{frame}

\section{任务实现}

\begin{frame}{任务总结}
    \begin{table}[!ht]
        \centering
        \begin{tabular}{|p{0.45\textwidth}|p{0.4\textwidth}|}
            \hline
                \textbf{大作业具体要求} & \textbf{完成情况} \\ \hline
                \textbf{1.} {\footnotesize 完成arkcompiler环境搭建和源码编译} & {\footnotesize 成功在docker环境中运行整个arkcompiler项目，能够将TS、JS代码编译生成最终的.abc可执行文件} \\ \hline
                \textbf{2.} {\footnotesize 完成 Assembler类各个接口的实现并提交pr至riscv-sig} & {\footnotesize 实现了RISCV相关的Assembler类的框架，并实现了其中RISCV-R型指令相关的接口，已将代码通过pr方式提交到riscv-sig} \\ \hline
                \textbf{3.} {\footnotesize 完成相应测试用例并提交pr至riscv-sig} & {\footnotesize 实现了AssemblerRiscv64Test测例运行框架，编写了RISCV-R型指令的测例。修改了ninja编译依赖，能够成功编译测例文件并运行。} \\ \hline
        \end{tabular}
    \end{table}
\end{frame}

\begin{frame}{任务分工}
    \begin{table}[]
        \begin{tabular}{|c|l|}
            \hline
            \textbf{组员}                   & \multicolumn{1}{c|}{\textbf{分工}} \\ \hline
            \multirow{3}{*}{\textbf{郝淼}}  & 1. 搭建assembler框架；                \\ \cline{2-2} 
                                          & 2. 搭建AssemblerRiscv64Test框架；     \\ \cline{2-2} 
                                          & 3. Slides展示汇报。                   \\ \hline
            \multirow{3}{*}{\textbf{李龙昊}} & 1. 修改BUILD.gn添加单元测试框架；           \\ \cline{2-2} 
                                          & 2. 编写RV32I-R型指令测例；               \\ \cline{2-2} 
                                          & 3. 报告文档撰写。                       \\ \hline
            \multirow{3}{*}{\textbf{陶思成}} & 1. 实现RISCV-R型指令对应的assembler函数；   \\ \cline{2-2} 
                                          & 2. 编写RV64I-R型指令测例；               \\ \cline{2-2} 
                                          & 3. Slides制作。                     \\ \hline
        \end{tabular}
    \end{table}
\end{frame}

\begin{frame}[fragile]{常数定义}

    {\small \quad 常数定义主要包括寄存器枚举类，RISCV-R类指令功能域枚举类。}

    \begin{columns}[t]
        \begin{column}{0.5\textwidth}

            \begin{lstlisting}[
                language=C++,
                basicstyle=\tiny\ttfamily,
                commentstyle=\color{darkgreen},
                numbers=none
                ]
// assembler_riscv64_constants.h
enum RegisterId : uint8_t {
    // all 32 registers
    X0, X1, SP, X3, X4, X5, X6, X7,
    ...
    X29, X30, X31,

    // all 32 registers‘ aliases
    ZERO = X0,
    ...
    T6 = X31,
    INVALID_REG = 0xFF,
};
    \end{lstlisting}

            \end{column}
            \begin{column}{0.5\textwidth}

            \begin{lstlisting}[
                language=C++,
                basicstyle=\tiny\ttfamily,
                commentstyle=\color{darkgreen},
                numbers=none]

// assembler_riscv64_constants.h
enum AddSubOpFunct {
    ADD     = 0x00000033,
    ... 
    SLTU    = 0x00003033,
};

... // other OpFunct enum

enum BitwiseOpFunct {
    XOR = 0x00004033,
    OR  = 0x00006033,
    AND = 0x00007033,
};
            \end{lstlisting}

        \end{column}
    \end{columns}    

    \begin{center}
        \textcolor{red}{这两类常数在后续宏定义中被指令模板使用}
    \end{center}
\end{frame}

\begin{frame}[fragile]{相关类的声明}

    {\small \quad 相关类的声明的重点是RISCV-R指令的声明}

    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        commentstyle=\color{darkgreen},
        numbers=none
        ]
// assembler_riscv64.h
// Integer Register-Register Operations (R-types)
void Add(const Register &rd, const Register &rs1, const Register &rs2);
void Addw(const Register &rd, const Register &rs1, const Register &rs2);
... 
void Or(const Register &rd, const Register &rs1, const Register &rs2);
void And(const Register &rd, const Register &rs1, const Register &rs2); 
    \end{lstlisting}
      
    \vspace{0.5cm}

    \begin{center}
        \textcolor{red}{这里进行了所有RISCV-R类型指令的声明， \\ 与后续这些指令的实现解耦合}
    \end{center}
\end{frame}


\begin{frame}[fragile]{相关类的实现}

    {\small \quad RISCV指令集中同一类型的指令结构统一，各个域的定义和处理具有统一性，因此我们使用宏定义模板的方法来完成相关类的实现。
    主要分为两大类宏，分别用于定义\textcolor{red}{指令各域宽度变量(用于提取各域数值)}，和定义\textcolor{red}{指令调用函数}}
    
\end{frame}

\begin{frame}[fragile]{指令各域宽度变量}

    {\small \quad 该类宏定义如下：}
    
    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        commentstyle=\color{darkgreen},
        numbers=none
        ]
// assembler_riscv64_constants.h
#define R_TYPE_FIELD_LIST(V)    \
    V(R_TYPE, opcode,  6,  0)   \
    ... 
    V(R_TYPE, funct7, 31, 25)

#define DECL_FIELDS_IN_INSTRUCTION(INSTNAME, FIELD_NAME, HIGHBITS, LOWBITS) \
static const uint32_t INSTNAME##_##FIELD_NAME##_HIGHBITS = HIGHBITS;  \
static const uint32_t INSTNAME##_##FIELD_NAME##_LOWBITS = LOWBITS;    \
static const uint32_t INSTNAME##_##FIELD_NAME##_WIDTH = 
                    ((HIGHBITS - LOWBITS) + 1); \
static const uint32_t INSTNAME##_##FIELD_NAME##_MASK = 
                    (((1 << INSTNAME##_##FIELD_NAME##_WIDTH) - 1) << LOWBITS);

#define DECL_INSTRUCTION_FIELDS(V)  \
    R_TYPE_FIELD_LIST(V)

DECL_INSTRUCTION_FIELDS(DECL_FIELDS_IN_INSTRUCTION)
    \end{lstlisting}

    {\small \quad 利用这些宏定义，我们可以得到如下变量，并用于指令调用函数中。}

    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        commentstyle=\color{darkgreen},
        numbers=none
        ]
// use opcode field as example
static const uint32_t R_TYPE_opcode_HIGHBITS = 6;
static const uint32_t R_TYPE_opcode_LOWBITS = 0;
static const uint32_t R_TYPE_opcode_WIDTH = 7;
static const uint32_t R_TYPE_opcode_MASK = 0x0000007f;
    \end{lstlisting}

\end{frame}

\begin{frame}[fragile]{指令调用函数(一)}

    {\small \quad 该类宏定义如下：}
    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        commentstyle=\color{darkgreen},
        numbers=none
        ]
#define EMIT_INSTS \
    EMIT_R_TYPE_INSTS(EMIT_R_TYPE_INST) \

#define EMIT_R_TYPE_INSTS(V) \
    V( Add,  ADD)            \
    ... 
    V( And,  AND)            \

#define EMIT_R_TYPE_INST(INSTNAME, INSTID) \
void AssemblerRiscv64::INSTNAME(const Register &rd, const Register &rs1, 
const Register &rs2) \
{ \
    uint32_t rd_id = Rd(rd.GetId()); \
    uint32_t rs1_id = Rs1(rs1.GetId()); \
    uint32_t rs2_id = Rs2(rs2.GetId()); \
    uint32_t code = rd_id | rs1_id | rs2_id | INSTID; \
    EmitU32(code); \
}
    \end{lstlisting}
\end{frame}

\begin{frame}[fragile]{指令调用函数(二)}

    {\small \quad 利用这些宏定义，我们可以得到如下指令调用函数：}  
    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        commentstyle=\color{darkgreen},
        numbers=none
        ]
// use Add as example
void AssemblerRiscv64::Add(const Register &rd, const Register &rs1, 
const Register &rs2) 
{ 
    uint32_t rd_id = Rd(rd.GetId()); 
    uint32_t rs1_id = Rs1(rs1.GetId()); 
    uint32_t rs2_id = Rs2(rs2.GetId()); 
    uint32_t code = rd_id | rs1_id | rs2_id | ADD; 
    EmitU32(code); 
}
    \end{lstlisting}

    \begin{center}
        \textcolor{red}{通过宏定义实现相关类，将相同操作模板和不同操作参数解耦合，
        极大地减少了代码的冗余，并提供了简单易用的实现框架。}
    \end{center}        
\end{frame}

\section{正确性测试}

\begin{frame}[fragile]{测试设计}

    {\small \quad 在测例部分，我们仿照另两种架构的实现，实现了riscv的测例类：AssemblerRiscv64Test，并编写了对应的测例，
    采用对拍的方式，调用我们的接口，查看生成的机器码是否与给定的预期结果相同，判断所写接口的正确性。}
 
    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        commentstyle=\color{darkgreen},
        numbers=none,
        stringstyle=\color{orange}
        ]
// assembler_riscv64_test.cpp
#define __ masm.
HWTEST_F_L0(AssemblerRiscv64Test, AddSub)
{
    std::string expectResult(
            "00000000:002080b3 \tadd\tra, ra, sp\n"
            "00000004:003100b3 \tadd\tra, sp, gp\n"
            ··· // other results
            );
    AssemblerRiscv64 masm(chunk_);
    __ Add(Register(RA), Register(RA), Register(SP));
    __ Add(Register(RA), Register(SP), Register(GP));
    ··· // other test
    std::ostringstream oss;
    DisassembleChunk(TARGET_RISCV64, &masm, oss);
    ASSERT_EQ(oss.str(), expectResult);
}
    \end{lstlisting}
      
\end{frame}

\begin{frame}{单元测试}

    {\small \quad 在尝试编译运行arkcompiler时，发现在其编译所有组件的过程中，会运行对应组件的单元测试，如果单元测试不能成功运行，将整体停止编译。}
    \\
    {\small \quad 一方面其他组件的单元测试，并不是我们测试的重点，它们的正确性，并不需要由我们测试；另一方面由于可能的运行环境问题，
    某些javascript相关组件的单元测试在本地不能成功的编译运行，这将导致arkcompiler不能正确的编译完成。}
    \\
    {\small \quad 为此，我们添加了\textcolor{red}{新的单元测试组ark\_compiler\_unittest}，并指定其编译时的单元测试动作，仅编译并运行\textcolor{red}{assembler相关的测例}，
    解决了上述问题，并大大节约了编译的时间成本。}

\end{frame}

\begin{frame}[fragile]{测试结果}

    {\small \quad 在完成ark环境的配置后，使用如下命令开始编译测例}
    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        keywordstyle=\color{darkgreen},
        numbers=none,
        morekeywords={build.py},
        alsoletter={.},
        ]
    build.py --product-name rk3568 --build-target ark_compiler_unittest
    \end{lstlisting}

    {\small \quad 由于我们在单元测试中指定了编译后立即运行测试的动作，所以编译测例成功也意味着测例运行通过。
    当然我们也可以用如下命令单独运行测例，并得到图\ref{fig:riscvi-result}的结果}
    
    \begin{lstlisting}[
        language=C++,
        basicstyle=\tiny\ttfamily,
        keywordstyle=\color{darkgreen},
        commentstyle=\color{darkgreen},
        stringstyle=\color{orange},
        numbers=none,
        morekeywords={build.py},
        alsoletter={.},
        ]
    out/rk3568/clang_x64/tests/unittest/arkcompiler/ets_runtime/AssemblerTest
    \end{lstlisting}

    \begin{figure}
        \centering
        \includegraphics[width=0.3\textwidth]{pic/rv64-test-result.png}
        \caption{RISCVI-R型指令测试结果}
        \label{fig:riscvi-result}
    \end{figure}


\end{frame}

\section{实验总结}
\begin{frame}{实验总结}

    \vspace{-0.3cm}

    {\large 实验贡献}

    {\small \quad 我们基于OpenHarmony Arkcompiler环境，为二进制翻译部件Assembler添加了到RISCVI-R型指令的支持。
    我们实现的\textcolor{red}{宏定义模板}为后续指令扩展提供了简单易用的接口，添加的\textcolor{red}{单元测试组}
    为后续测试搭建了简单易用的框架。}

    \vspace{0.3cm}

    {\large 参考资料}

    \begin{itemize}
        \item \highlightedhref{https://gitee.com/openharmony/community/blob/master/sig/sig_compileruntime/sig_compileruntime_cn.md}{Arkcompiler README}
        \item \highlightedhref{https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf}{RISCV ISA Manual}
    \end{itemize}  

    \vspace{0.3cm}

    {\large 代码仓库}

    \quad \highlightedhref{https://gitee.com/advanced_os_group1/arkcompiler_ets_runtime}{advanced\_os\_group1/arkcompiler\_ets\_runtime}

\end{frame}



\begin{frame}
    \begin{center}
        {\Huge 谢谢！}

        \vspace{0.4cm}

        {\Huge 恳请批评指正！}
    \end{center}
\end{frame}

\end{document}